package main

import (
	"fmt"
	"net/http"
	"time"
	"web_framework/config"
	"web_framework/model"
	"web_framework/storage"
	"web_framework/websocket/v1/handler"
	"web_framework/websocket/v1/router/connection"

	"github.com/gorilla/websocket"
	"github.com/pkg/errors"
	log "github.com/sirupsen/logrus"
	"github.com/spf13/pflag"
)

var (
	upgrader = websocket.Upgrader{
		// 读取存储空间大小
		ReadBufferSize: 1024,
		// 写入存储空间大小
		WriteBufferSize: 1024,
		// 允许跨域
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	}
)

var (
	cfg     = pflag.StringP("config", "c", "", "apiserver config file path.")
	version = pflag.BoolP("version", "v", false, "show version info.")
)

type User struct {
	//用户名称
	userName string
	//存放链接
	conn *connection.Connection
	//状态
	status bool
}

func init() {
	handler.Holder = &handler.ServiceHolder{
		make(map[int]handler.Service),
	}
	//注册服务
	handler.Holder.RegisterService(201, new(handler.HeartHandle))
	handler.Holder.RegisterService(1, new(handler.LoginHandle))

}
func main() {
	// init config
	if err := config.Init(*cfg); err != nil {
		panic(err)
	}

	setMySQLConnection()
	setRedisPool()

	// 当有请求访问ws时，执行此回调方法
	//router := gin.Default()
	//router.Use(Validate())  //使用validate()中间件身份验证
	//router.GET("/ws", wsHand)
	http.HandleFunc("/ws", wsHand)
	//router.Run(":8089") //localhost:8989/
	err := http.ListenAndServe(":8089", nil)
	if err != nil {
		log.Fatal("ListenAndServe", err.Error())
	}

}

func wsHand(res http.ResponseWriter, req *http.Request) {
	if err := wsHandler(res, req); err != nil {
		return
	}
}

func wsHandler(w http.ResponseWriter, r *http.Request) (err error) {

	var (
		wsConn *websocket.Conn
		conn   *connection.Connection
	)
	// 完成http应答，在httpheader中放下如下参数
	if wsConn, err = upgrader.Upgrade(w, r, nil); err != nil {
		return // 获取连接失败直接返回
	}

	if err = loginCheck(wsConn); err != nil {
		wsConn.Close()
		return
	}
	if conn, err = connection.InitConnection(wsConn); err != nil {
		return
	}

	//TODO 建立连接后写入Redis
	var myuser User
	myuser.conn = conn
	myuser.status = true
	return
}

//对身份进行验证
func loginCheck(wsConn *websocket.Conn) (err error) {
	ch := make(chan model.Request)
	defer close(ch)
	var data model.Request

	// 并发执行一个函数
	go func() {
		if err = wsConn.ReadJSON(&data); err != nil {
			wsConn.Close()
			return
		}
		ch <- data

	}()

	select {
	case <-ch:
		//登录信息验证
		fmt.Println("data", data)
		err = handler.Holder.Login(1, data, wsConn)
		return
	case <-time.After(10 * time.Second):
		err = errors.New("connect timeout")
		return
	}
}

func setMySQLConnection() error {
	log.WithField("DB type", config.C.DB.Type).WithField("dsn", config.C.DB.DSN).Info("connecting to DB")
	db, err := storage.OpenDatabase(config.C.DB.Type, config.C.DB.DSN)
	if err != nil {
		return errors.Wrap(err, "database connection error")
	}
	config.C.DB.DB = db
	return nil
}

func setRedisPool() error {
	log.WithField("url", config.C.Redis.URL).Info("setup redis connection pool")
	err := storage.InitRedisPool(config.C.Redis.URL)
	return err
}
